<!DOCTYPE html>
<html>
<head><meta name="generator" content="Hexo 3.8.0">
  <meta charset="utf-8">
  

  
  <title>shiro综合实例 | Hexo</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <meta name="description" content="综合实例简单数据字典">
<meta name="keywords" content="shiro">
<meta property="og:type" content="article">
<meta property="og:title" content="shiro综合实例">
<meta property="og:url" content="http://yoursite.com/2018/10/12/2018-03-19-shiro综合实例/index.html">
<meta property="og:site_name" content="Hexo">
<meta property="og:description" content="综合实例简单数据字典">
<meta property="og:locale" content="default">
<meta property="og:image" content="https://img.w3cschool.cn/attachments/image/wk/shiro/19.png">
<meta property="og:image" content="http://p1aoqp63y.bkt.clouddn.com/QQ%E6%88%AA%E5%9B%BE20180319152042.png">
<meta property="og:image" content="http://p1aoqp63y.bkt.clouddn.com/QQ%E6%88%AA%E5%9B%BE20180319152306.png">
<meta property="og:image" content="http://p1aoqp63y.bkt.clouddn.com/QQ%E6%88%AA%E5%9B%BE20180319152415.png">
<meta property="og:image" content="http://p1aoqp63y.bkt.clouddn.com/QQ%E6%88%AA%E5%9B%BE20180319152521.png">
<meta property="og:image" content="http://p1aoqp63y.bkt.clouddn.com/QQ%E6%88%AA%E5%9B%BE20180319152605.png">
<meta property="og:image" content="http://p1aoqp63y.bkt.clouddn.com/QQ%E6%88%AA%E5%9B%BE20180319152715.png">
<meta property="og:image" content="http://p1aoqp63y.bkt.clouddn.com/QQ%E6%88%AA%E5%9B%BE20180319152807.png">
<meta property="og:image" content="http://p1aoqp63y.bkt.clouddn.com/QQ%E6%88%AA%E5%9B%BE20180319152849.png">
<meta property="og:updated_time" content="2018-11-01T14:24:04.945Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="shiro综合实例">
<meta name="twitter:description" content="综合实例简单数据字典">
<meta name="twitter:image" content="https://img.w3cschool.cn/attachments/image/wk/shiro/19.png">
  
    <link rel="alternate" href="/org/atom.xml" title="Hexo" type="application/atom+xml">
  
  
    <link rel="icon" href="/favicon.png">
  
  
    <link href="//fonts.googleapis.com/css?family=Source+Code+Pro" rel="stylesheet" type="text/css">
  
  <link rel="stylesheet" href="/org/css/style.css">
</head>
</html>
<body>
  <div id="container">
    <div id="wrap">
      <header id="header">
  <div id="banner"></div>
  <div id="header-outer" class="outer">
    <div id="header-title" class="inner">
      <h1 id="logo-wrap">
        <a href="/org/" id="logo">Hexo</a>
      </h1>
      
    </div>
    <div id="header-inner" class="inner">
      <nav id="main-nav">
        <a id="main-nav-toggle" class="nav-icon"></a>
        
          <a class="main-nav-link" href="/org/">Home</a>
        
          <a class="main-nav-link" href="/org/archives">Archives</a>
        
      </nav>
      <nav id="sub-nav">
        
          <a id="nav-rss-link" class="nav-icon" href="/org/atom.xml" title="RSS Feed"></a>
        
        <a id="nav-search-btn" class="nav-icon" title="Search"></a>
      </nav>
      <div id="search-form-wrap">
        <form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit">&#xF002;</button><input type="hidden" name="sitesearch" value="http://yoursite.com"></form>
      </div>
    </div>
  </div>
</header>
      <div class="outer">
        <section id="main"><article id="post-2018-03-19-shiro综合实例" class="article article-type-post" itemscope="" itemprop="blogPost">
  <div class="article-meta">
    <a href="/org/2018/10/12/2018-03-19-shiro综合实例/" class="article-date">
  <time datetime="2018-10-12T09:03:30.000Z" itemprop="datePublished">2018-10-12</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 class="article-title" itemprop="name">
      shiro综合实例
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h2 id="综合实例"><a href="#综合实例" class="headerlink" title="综合实例"></a>综合实例</h2><p><img src="https://img.w3cschool.cn/attachments/image/wk/shiro/19.png" alt="img">简单数据字典</p>
<a id="more"></a>
<h2 id="简单数据字典"><a href="#简单数据字典" class="headerlink" title="简单数据字典"></a>简单数据字典</h2><p>用户 (sys_user)</p>
<table>
<thead>
<tr>
<th>名称</th>
<th>类型</th>
<th>长度</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>id</td>
<td>bigint</td>
<td></td>
<td>编号 主键</td>
</tr>
<tr>
<td>username</td>
<td>varchar</td>
<td>100</td>
<td>用户名</td>
</tr>
<tr>
<td>password</td>
<td>varchar</td>
<td>100</td>
<td>密码</td>
</tr>
<tr>
<td>salt</td>
<td>varchar</td>
<td>50</td>
<td>盐</td>
</tr>
<tr>
<td>role_ids</td>
<td>varchar</td>
<td>100</td>
<td>角色列表</td>
</tr>
<tr>
<td>locked</td>
<td>bool</td>
<td></td>
<td>账户是否锁定</td>
</tr>
</tbody>
</table>
<p>组织机构 (sys_organization)</p>
<table>
<thead>
<tr>
<th>名称</th>
<th>类型</th>
<th>长度</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>id</td>
<td>bigint</td>
<td></td>
<td>编号 主键</td>
</tr>
<tr>
<td>name</td>
<td>varchar</td>
<td>100</td>
<td>组织机构名</td>
</tr>
<tr>
<td>priority</td>
<td>int</td>
<td></td>
<td>显示顺序</td>
</tr>
<tr>
<td>parent_id</td>
<td>bigint</td>
<td></td>
<td>父编号</td>
</tr>
<tr>
<td>parent_ids</td>
<td>varchar</td>
<td>100</td>
<td>父编号列表</td>
</tr>
<tr>
<td>available</td>
<td>bool</td>
<td></td>
<td>是否可用</td>
</tr>
</tbody>
</table>
<p>资源 (sys_resource)</p>
<table>
<thead>
<tr>
<th>名称</th>
<th>类型</th>
<th>长度</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>id</td>
<td>bigint</td>
<td></td>
<td>编号 主键</td>
</tr>
<tr>
<td>name</td>
<td>varchar</td>
<td>100</td>
<td>资源名称</td>
</tr>
<tr>
<td>type</td>
<td>varchar</td>
<td>50</td>
<td>资源类型，</td>
</tr>
<tr>
<td>priority</td>
<td>int</td>
<td></td>
<td>显示顺序</td>
</tr>
<tr>
<td>parent_id</td>
<td>bigint</td>
<td></td>
<td>父编号</td>
</tr>
<tr>
<td>parent_ids</td>
<td>varchar</td>
<td>100</td>
<td>父编号列表</td>
</tr>
<tr>
<td>permission</td>
<td>varchar</td>
<td>100</td>
<td>权限字符串</td>
</tr>
<tr>
<td>available</td>
<td>bool</td>
<td></td>
<td>是否可用</td>
</tr>
</tbody>
</table>
<p>角色 (sys_role)</p>
<table>
<thead>
<tr>
<th>名称</th>
<th>类型</th>
<th>长度</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>id</td>
<td>bigint</td>
<td></td>
<td>编号 主键</td>
</tr>
<tr>
<td>role</td>
<td>varchar</td>
<td>100</td>
<td>角色名称</td>
</tr>
<tr>
<td>description</td>
<td>varchar</td>
<td>100</td>
<td>角色描述</td>
</tr>
<tr>
<td>resource_ids</td>
<td>varchar</td>
<td>100</td>
<td>授权的资源</td>
</tr>
<tr>
<td>available</td>
<td>bool</td>
<td></td>
<td>是否可用</td>
</tr>
</tbody>
</table>
<p><strong>资源</strong>：表示菜单元素，页面按钮元素等；菜单元素用来显示界面菜单的，页面按钮是每个页面可进行的操作，如新增，修改，删除按钮；使用type来区分元素类型(如menu表示菜单，button代表按钮),priority是元素的排序，如菜单显示顺序；permission表示权限；如用户菜单使用<code>user:*</code>;也就是把菜单授权给用户后，用户就拥有了<code>user:*</code>权限；如用户新增按钮使用user:create,也就是把用户新增按钮授权给用户后，用户就拥有了 user:create 权限了；available 表示资源是否可用，如菜单显示 / 不显示。</p>
<p><strong>角色</strong>：role 表示角色标识符，如 admin，用于后台判断使用；description 表示角色描述，如超级管理员，用于前端显示给用户使用；resource_ids 表示该角色拥有的资源列表，即该角色拥有的权限列表（显示角色），即角色是权限字符串集合；available 表示角色是否可用。</p>
<p><strong>组织机构</strong>：name 表示组织机构名称，priority 是组织机构的排序，即显示顺序；available 表示组织机构是否可用。</p>
<p><strong>用户</strong>：username 表示用户名；password 表示密码；salt 表示加密密码的盐；role_ids 表示用户拥有的角色列表，可以通过角色再获取其权限字符串列表；locked 表示用户是否锁定。</p>
<p>此处如资源、组织机构都是树型结构：</p>
<table>
<thead>
<tr>
<th>id</th>
<th>name</th>
<th>parent_id</th>
<th>parent_ids</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>总公司</td>
<td>0</td>
<td>0/</td>
</tr>
<tr>
<td>2</td>
<td>山东分公司</td>
<td>1</td>
<td>0/1/</td>
</tr>
<tr>
<td>3</td>
<td>河北分公司</td>
<td>1</td>
<td>0/1/</td>
</tr>
<tr>
<td>4</td>
<td>济南分公司</td>
<td>2</td>
<td>0/1/2/</td>
</tr>
</tbody>
</table>
<p>parent_id 表示父编号，parent_ids 表示所有祖先编号；如 0/1/2/ 表示其祖先是 2、1、0；其中根节点父编号为 0。</p>
<p>为了简单性，如用户 - 角色，角色 - 资源关系直接在实体（用户表中的 role_ids，角色表中的 resource_ids）里完成的，没有建立多余的关系表，如要查询拥有 admin 角色的用户时，建议建立关联表，否则就没必要建立了。在存储关系时如 role_ids=1,2,3,；多个之间使用逗号分隔。</p>
<p>用户组、组织机构组本实例没有实现，即可以把一组权限授权给这些组，组中的用户 / 组织机构就自动拥有这些角色 / 权限了；另外对于用户组可以实现一个默认用户组，如论坛，不管匿名 / 登录用户都有查看帖子的权限。</p>
<h2 id="表-数据-SQL"><a href="#表-数据-SQL" class="headerlink" title="表 / 数据 SQL"></a>表 / 数据 SQL</h2><p>具体请参考</p>
<ul>
<li>sql/ shiro-schema.sql （表结构）</li>
<li>sql/ shiro-data.sql （初始数据）</li>
</ul>
<p>默认用户名 / 密码是 admin/123456。</p>
<h2 id="实体"><a href="#实体" class="headerlink" title="实体"></a>实体</h2><p>具体请参考 com.github.zhangkaitao.shiro.chapter16.entity 包下的实体，此处就不列举了。</p>
<h2 id="DAO"><a href="#DAO" class="headerlink" title="DAO"></a>DAO</h2><p>具体请参考 com.github.zhangkaitao.shiro.chapter16.dao 包下的 DAO 接口及实现。</p>
<h2 id="Service"><a href="#Service" class="headerlink" title="Service"></a>Service</h2><p>具体请参考 com.github.zhangkaitao.shiro.chapter16.service 包下的 Service 接口及实现。以下是出了基本 CRUD 之外的关键接口：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">public interface ResourceService &#123;</span><br><span class="line">    Set&lt;String&gt; findPermissions(Set&lt;Long&gt; resourceIds); //得到资源对应的权限字符串</span><br><span class="line">    List&lt;Resource&gt; findMenus(Set&lt;String&gt; permissions); //根据用户权限得到菜单</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">public interface RoleService &#123;</span><br><span class="line">    Set&lt;String&gt; findRoles(Long... roleIds); //根据角色编号得到角色标识符列表</span><br><span class="line">    Set&lt;String&gt; findPermissions(Long[] roleIds); //根据角色编号得到权限字符串列表</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">public interface UserService &#123;</span><br><span class="line">    public void changePassword(Long userId, String newPassword); //修改密码</span><br><span class="line">    public User findByUsername(String username); //根据用户名查找用户</span><br><span class="line">    public Set&lt;String&gt; findRoles(String username);// 根据用户名查找其角色</span><br><span class="line">    public Set&lt;String&gt; findPermissions(String username);// 根据用户名查找其权限</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>Service 实现请参考源代码，此处就不列举了。</p>
<h2 id="UserRealm-实现"><a href="#UserRealm-实现" class="headerlink" title="UserRealm 实现"></a>UserRealm 实现</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">public class UserRealm extends AuthorizingRealm &#123;</span><br><span class="line">    @Autowired private UserService userService;</span><br><span class="line">    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) &#123;</span><br><span class="line">        String username = (String)principals.getPrimaryPrincipal();</span><br><span class="line">        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();</span><br><span class="line">        authorizationInfo.setRoles(userService.findRoles(username));</span><br><span class="line">        authorizationInfo.setStringPermissions(userService.findPermissions(username));</span><br><span class="line">        System.out.println(userService.findPermissions(username));</span><br><span class="line">        return authorizationInfo;</span><br><span class="line">    &#125;</span><br><span class="line">    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException &#123;</span><br><span class="line">        String username = (String)token.getPrincipal();</span><br><span class="line">        User user = userService.findByUsername(username);</span><br><span class="line">        if(user == null) &#123;</span><br><span class="line">            throw new UnknownAccountException();//没找到帐号</span><br><span class="line">        &#125;</span><br><span class="line">        if(Boolean.TRUE.equals(user.getLocked())) &#123;</span><br><span class="line">            throw new LockedAccountException(); //帐号锁定</span><br><span class="line">        &#125;</span><br><span class="line">        return new SimpleAuthenticationInfo(</span><br><span class="line">                user.getUsername(), //用户名</span><br><span class="line">                user.getPassword(), //密码</span><br><span class="line">                ByteSource.Util.bytes(user.getCredentialsSalt()),//salt=username+salt</span><br><span class="line">                getName()  //realm name</span><br><span class="line">        );</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>此处的 UserRealm 和《第六章 Realm 及相关对象》中的 UserRealm 类似，通过 UserService 获取帐号及角色 / 权限信息。</p>
<h2 id="Web-层控制器"><a href="#Web-层控制器" class="headerlink" title="Web 层控制器"></a>Web 层控制器</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">@Controller</span><br><span class="line">public class IndexController &#123;</span><br><span class="line">    @Autowired</span><br><span class="line">    private ResourceService resourceService;</span><br><span class="line">    @Autowired</span><br><span class="line">    private UserService userService;</span><br><span class="line">    @RequestMapping(&quot;/&quot;)</span><br><span class="line">    public String index(@CurrentUser User loginUser, Model model) &#123;</span><br><span class="line">        Set&lt;String&gt; permissions = userService.findPermissions(loginUser.getUsername());</span><br><span class="line">        List&lt;Resource&gt; menus = resourceService.findMenus(permissions);</span><br><span class="line">        model.addAttribute(&quot;menus&quot;, menus);</span><br><span class="line">        return &quot;index&quot;;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>IndexController 中查询菜单在前台界面显示，请参考相应的 jsp 页面；</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">@Controller</span><br><span class="line">public class LoginController &#123;</span><br><span class="line">    @RequestMapping(value = &quot;/login&quot;)</span><br><span class="line">    public String showLoginForm(HttpServletRequest req, Model model) &#123;</span><br><span class="line">        String exceptionClassName = (String)req.getAttribute(&quot;shiroLoginFailure&quot;);</span><br><span class="line">        String error = null;</span><br><span class="line">        if(UnknownAccountException.class.getName().equals(exceptionClassName)) &#123;</span><br><span class="line">            error = &quot;用户名/密码错误&quot;;</span><br><span class="line">        &#125; else if(IncorrectCredentialsException.class.getName().equals(exceptionClassName)) &#123;</span><br><span class="line">            error = &quot;用户名/密码错误&quot;;</span><br><span class="line">        &#125; else if(exceptionClassName != null) &#123;</span><br><span class="line">            error = &quot;其他错误：&quot; + exceptionClassName;</span><br><span class="line">        &#125;</span><br><span class="line">        model.addAttribute(&quot;error&quot;, error);</span><br><span class="line">        return &quot;login&quot;;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>LoginController 用于显示登录表单页面，其中 shiro authc 拦截器进行登录，登录失败的话会把错误存到 shiroLoginFailure 属性中，在该控制器中获取后来显示相应的错误信息。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">@RequiresPermissions(&quot;resource:view&quot;)</span><br><span class="line">@RequestMapping(method = RequestMethod.GET)</span><br><span class="line">public String list(Model model) &#123;</span><br><span class="line">    model.addAttribute(&quot;resourceList&quot;, resourceService.findAll());</span><br><span class="line">    return &quot;resource/list&quot;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>在控制器方法上使用 @RequiresPermissions 指定需要的权限信息，其他的都是类似的，请参考源码。</p>
<h2 id="Web-层标签库"><a href="#Web-层标签库" class="headerlink" title="Web 层标签库"></a>Web 层标签库</h2><p>com.github.zhangkaitao.shiro.chapter16.web.taglib.Functions 提供了函数标签实现，有根据编号显示资源 / 角色 / 组织机构名称，其定义放在 src/main/webapp/tld/zhang-functions.tld。</p>
<h2 id="Web-层异常处理器"><a href="#Web-层异常处理器" class="headerlink" title="Web 层异常处理器"></a>Web 层异常处理器</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">@ControllerAdvice</span><br><span class="line">public class DefaultExceptionHandler &#123;</span><br><span class="line">    @ExceptionHandler(&#123;UnauthorizedException.class&#125;)</span><br><span class="line">    @ResponseStatus(HttpStatus.UNAUTHORIZED)</span><br><span class="line">    public ModelAndView processUnauthenticatedException(NativeWebRequest request, UnauthorizedException e) &#123;</span><br><span class="line">        ModelAndView mv = new ModelAndView();</span><br><span class="line">        mv.addObject(&quot;exception&quot;, e);</span><br><span class="line">        mv.setViewName(&quot;unauthorized&quot;);</span><br><span class="line">        return mv;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>如果抛出 UnauthorizedException，将被该异常处理器截获来显示没有权限信息。</p>
<h2 id="Spring-配置——spring-config-xml"><a href="#Spring-配置——spring-config-xml" class="headerlink" title="Spring 配置——spring-config.xml"></a>Spring 配置——spring-config.xml</h2><p>定义了 context:component-scan 来扫描除 web 层的组件、dataSource（数据源）、事务管理器及事务切面等；具体请参考配置源码。</p>
<h2 id="Spring-配置——spring-config-cache-xml"><a href="#Spring-配置——spring-config-cache-xml" class="headerlink" title="Spring 配置——spring-config-cache.xml"></a>Spring 配置——spring-config-cache.xml</h2><p>定义了 spring 通用 cache，使用 ehcache 实现；具体请参考配置源码。</p>
<p>userRealm 组件禁用掉了 cache，可以参考 <a href="https://github.com/zhangkaitao/es/tree/master/web/src/main/java/com/sishuok/es/extra/aop" target="_blank" rel="noopener">https://github.com/zhangkaitao/es/tree/master/web/src/main/java/com/sishuok/es/extra/aop</a> 实现自己的 cache 切面；否则需要在修改如资源 / 角色等信息时清理掉缓存。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&lt;bean id=&quot;sysUserFilter&quot; </span><br><span class="line">class=&quot;com.github.zhangkaitao.shiro.chapter16.web.shiro.filter.SysUserFilter&quot;/&gt;</span><br></pre></td></tr></table></figure>
<p>sysUserFilter 用于根据当前登录用户身份获取 User 信息放入 request；然后就可以通过 request 获取 User。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">&lt;property name=&quot;filterChainDefinitions&quot;&gt;</span><br><span class="line">  &lt;value&gt;</span><br><span class="line">    /login = authc</span><br><span class="line">    /logout = logout</span><br><span class="line">    /authenticated = authc</span><br><span class="line">    /** = user,sysUser</span><br><span class="line">  &lt;/value&gt;</span><br><span class="line">&lt;/property&gt;</span><br></pre></td></tr></table></figure>
<p>如上是 shiroFilter 的 filterChainDefinitions 定义。</p>
<h2 id="Spring-MVC-配置——spring-mvc-xml"><a href="#Spring-MVC-配置——spring-mvc-xml" class="headerlink" title="Spring MVC 配置——spring-mvc.xml"></a>Spring MVC 配置——spring-mvc.xml</h2><p>定义了 spring mvc 相关组件。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&lt;mvc:annotation-driven&gt;</span><br><span class="line">  &lt;mvc:argument-resolvers&gt;</span><br><span class="line">    &lt;bean class=&quot;com.github.zhangkaitao.shiro.chapter16</span><br><span class="line">        .web.bind.method.CurrentUserMethodArgumentResolver&quot;/&gt;</span><br><span class="line">  &lt;/mvc:argument-resolvers&gt;</span><br><span class="line">&lt;/mvc:annotation-driven&gt;</span><br></pre></td></tr></table></figure>
<p>此处注册了一个 @CurrentUser 参数解析器。如之前的 IndexController，从 request 获取 shiro sysUser 拦截器放入的当前登录 User 对象。</p>
<h2 id="Spring-MVC-配置——spring-mvc-shiro-xml"><a href="#Spring-MVC-配置——spring-mvc-shiro-xml" class="headerlink" title="Spring MVC 配置——spring-mvc-shiro.xml"></a>Spring MVC 配置——spring-mvc-shiro.xml</h2><p>定义了 spring mvc 相关组件。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&lt;aop:config proxy-target-class=&quot;true&quot;&gt;&lt;/aop:config&gt;</span><br><span class="line">&lt;bean class=&quot;org.apache.shiro.spring.security</span><br><span class="line">    .interceptor.AuthorizationAttributeSourceAdvisor&quot;&gt;</span><br><span class="line">  &lt;property name=&quot;securityManager&quot; ref=&quot;securityManager&quot;/&gt;</span><br><span class="line">&lt;/bean&gt;</span><br></pre></td></tr></table></figure>
<p>定义 aop 切面，用于代理如 @RequiresPermissions 注解的控制器，进行权限控制。</p>
<h2 id="web-xml-配置文件"><a href="#web-xml-配置文件" class="headerlink" title="web.xml 配置文件"></a>web.xml 配置文件</h2><p>定义 Spring ROOT 上下文加载器、ShiroFilter、及 SpringMVC 拦截器。具体请参考源码。</p>
<h2 id="JSP-页面"><a href="#JSP-页面" class="headerlink" title="JSP 页面"></a>JSP 页面</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&lt;shiro:hasPermission name=&quot;user:create&quot;&gt;</span><br><span class="line">    &lt;a href=&quot;$&#123;pageContext.request.contextPath&#125;/user/create&quot;&gt;用户新增&lt;/a&gt;&lt;br/&gt;</span><br><span class="line">&lt;/shiro:hasPermission&gt;</span><br></pre></td></tr></table></figure>
<h2 id="系统截图"><a href="#系统截图" class="headerlink" title="系统截图"></a>系统截图</h2><p>访问 <a href="http://localhost:8080/chapter16/" target="_blank" rel="noopener">http://localhost:8080/chapter16/</a>；<br>首先进入登录页面，输入用户名 / 密码（默认 admin/123456）登录：</p>
<p><img src="http://p1aoqp63y.bkt.clouddn.com/QQ%E6%88%AA%E5%9B%BE20180319152042.png" alt="2"></p>
<p>登录成功后到达整个页面主页，并根据当前用户权限显示相应的菜单，此处菜单比较简单，没有树型结构显示</p>
<p><img src="http://p1aoqp63y.bkt.clouddn.com/QQ%E6%88%AA%E5%9B%BE20180319152306.png" alt="3"></p>
<p>组织结构管理</p>
<p><img src="http://p1aoqp63y.bkt.clouddn.com/QQ%E6%88%AA%E5%9B%BE20180319152415.png" alt="orgManager"></p>
<p>用户管理</p>
<p><img src="http://p1aoqp63y.bkt.clouddn.com/QQ%E6%88%AA%E5%9B%BE20180319152521.png" alt="user"></p>
<p>用户新增</p>
<p><img src="http://p1aoqp63y.bkt.clouddn.com/QQ%E6%88%AA%E5%9B%BE20180319152605.png" alt="user:add"></p>
<p>资源管理</p>
<p><img src="http://p1aoqp63y.bkt.clouddn.com/QQ%E6%88%AA%E5%9B%BE20180319152715.png" alt="resource:manager"></p>
<p>角色管理</p>
<p><img src="http://p1aoqp63y.bkt.clouddn.com/QQ%E6%88%AA%E5%9B%BE20180319152807.png" alt="role"></p>
<p>新增角色</p>
<p><img src="http://p1aoqp63y.bkt.clouddn.com/QQ%E6%88%AA%E5%9B%BE20180319152849.png" alt="role:add"></p>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://yoursite.com/2018/10/12/2018-03-19-shiro综合实例/" data-id="cjoztxu3f00161wijqgjzfrys" class="article-share-link">Share</a>
      
      
  <ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/org/tags/shiro/">shiro</a></li></ul>

    </footer>
  </div>
  
    
<nav id="article-nav">
  
    <a href="/org/2018/10/12/2018-03-17-shiro的缓存机制/" id="article-nav-newer" class="article-nav-link-wrap">
      <strong class="article-nav-caption">Newer</strong>
      <div class="article-nav-title">
        
          shiro缓存机制
        
      </div>
    </a>
  
  
    <a href="/org/2018/10/12/2018-03-19-shiro并发控制/" id="article-nav-older" class="article-nav-link-wrap">
      <strong class="article-nav-caption">Older</strong>
      <div class="article-nav-title">shiro并发登录控制</div>
    </a>
  
</nav>

  
</article>

</section>
        
          <aside id="sidebar">
  
    

  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Tags</h3>
    <div class="widget">
      <ul class="tag-list"><li class="tag-list-item"><a class="tag-list-link" href="/org/tags/SVN/">SVN</a></li><li class="tag-list-item"><a class="tag-list-link" href="/org/tags/Spring-secrity/">Spring-secrity</a></li><li class="tag-list-item"><a class="tag-list-link" href="/org/tags/hexo/">hexo</a></li><li class="tag-list-item"><a class="tag-list-link" href="/org/tags/hibenrate/">hibenrate</a></li><li class="tag-list-item"><a class="tag-list-link" href="/org/tags/jekyll/">jekyll</a></li><li class="tag-list-item"><a class="tag-list-link" href="/org/tags/jenkins/">jenkins</a></li><li class="tag-list-item"><a class="tag-list-link" href="/org/tags/redis/">redis</a></li><li class="tag-list-item"><a class="tag-list-link" href="/org/tags/shiro/">shiro</a></li><li class="tag-list-item"><a class="tag-list-link" href="/org/tags/spingMVC/">spingMVC</a></li><li class="tag-list-item"><a class="tag-list-link" href="/org/tags/spring-cloud/">spring cloud</a></li><li class="tag-list-item"><a class="tag-list-link" href="/org/tags/spring-cloud/">spring-cloud</a></li><li class="tag-list-item"><a class="tag-list-link" href="/org/tags/spring-secrity/">spring-secrity</a></li><li class="tag-list-item"><a class="tag-list-link" href="/org/tags/springMVC/">springMVC</a></li><li class="tag-list-item"><a class="tag-list-link" href="/org/tags/springboot/">springboot</a></li><li class="tag-list-item"><a class="tag-list-link" href="/org/tags/生活/">生活</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Tag Cloud</h3>
    <div class="widget tagcloud">
      <a href="/org/tags/SVN/" style="font-size: 12px;">SVN</a> <a href="/org/tags/Spring-secrity/" style="font-size: 10px;">Spring-secrity</a> <a href="/org/tags/hexo/" style="font-size: 10px;">hexo</a> <a href="/org/tags/hibenrate/" style="font-size: 10px;">hibenrate</a> <a href="/org/tags/jekyll/" style="font-size: 10px;">jekyll</a> <a href="/org/tags/jenkins/" style="font-size: 10px;">jenkins</a> <a href="/org/tags/redis/" style="font-size: 16px;">redis</a> <a href="/org/tags/shiro/" style="font-size: 18px;">shiro</a> <a href="/org/tags/spingMVC/" style="font-size: 10px;">spingMVC</a> <a href="/org/tags/spring-cloud/" style="font-size: 10px;">spring cloud</a> <a href="/org/tags/spring-cloud/" style="font-size: 10px;">spring-cloud</a> <a href="/org/tags/spring-secrity/" style="font-size: 12px;">spring-secrity</a> <a href="/org/tags/springMVC/" style="font-size: 14px;">springMVC</a> <a href="/org/tags/springboot/" style="font-size: 20px;">springboot</a> <a href="/org/tags/生活/" style="font-size: 10px;">生活</a>
    </div>
  </div>

  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Archives</h3>
    <div class="widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/org/archives/2018/11/">November 2018</a></li><li class="archive-list-item"><a class="archive-list-link" href="/org/archives/2018/10/">October 2018</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Recent Posts</h3>
    <div class="widget">
      <ul>
        
          <li>
            <a href="/org/2018/11/27/redis07-zookeeper-kafka集群部署以及如何使用简单介绍/">redis07-zookeeper+kafka集群部署以及如何使用简单介绍</a>
          </li>
        
          <li>
            <a href="/org/2018/11/13/redis06-cluster实现高可用性/">redis06-cluster实现高可用性</a>
          </li>
        
          <li>
            <a href="/org/2018/11/12/redis05-在项目中搭建读写分-高可用-多master的redis-cluster集群/">redis05-在项目中搭建读写分+高可用+多master的redis cluster集群</a>
          </li>
        
          <li>
            <a href="/org/2018/11/05/在项目中用经典的三节点方式部署哨兵集群-笔记/">在项目中用经典的三节点方式部署哨兵集群-笔记</a>
          </li>
        
          <li>
            <a href="/org/2018/11/05/redis哨兵的多个核心底层原理-笔记/">redis哨兵的多个核心底层原理-笔记</a>
          </li>
        
      </ul>
    </div>
  </div>

  
</aside>
        
      </div>
      <footer id="footer">
  
  <div class="outer">
    <div id="footer-info" class="inner">
      &copy; 2018 John Doe<br>
      Powered by <a href="http://hexo.io/" target="_blank">Hexo</a>
    </div>
  </div>
</footer>
    </div>
    <nav id="mobile-nav">
  
    <a href="/org/" class="mobile-nav-link">Home</a>
  
    <a href="/org/archives" class="mobile-nav-link">Archives</a>
  
</nav>
    

<script src="//code.jquery.com/jquery-2.0.3.min.js"></script>


  <link rel="stylesheet" href="/org/fancybox/jquery.fancybox.css">
  <script src="/org/fancybox/jquery.fancybox.pack.js"></script>


<script src="/org/js/script.js"></script>



  </div>
</body>
</html>